package com.caifu.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.caifu.bean.Result;
import com.caifu.bean.ResultUtil;
import com.caifu.pojo.*;
import com.caifu.service.*;
import com.caifu.util.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;

/**
 * @Auther: szt
 * @Date: 2020/11/24 19:57
 * @Description:
 */
@Controller
@ApiIgnore
public class LoginController extends AbstractController {

    final static Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private SysMenuService menuService;
    @Autowired
    private SysUserService userService;
    @Autowired
    private SysLogService logService;
    @Autowired
    private SysOrganizationService orgService;

    //跳到登录页
    @RequestMapping(value = {"", "/", "/login", "login"})
    public String login(ModelMap model, Integer type) {
        if (type == null) {
            type = 0;
        }
        model.put("type", type);
        return "view/sys/login";
    }

    //登陆
    @RequestMapping("/authentication")
    @ResponseBody
    public JSONObject authentication(SysUser user) throws Exception {
        SysUser oldUser = new SysUser();
        JSONObject obj = new JSONObject();
        int code = 200;
        String msg = "登陆成功！";
        Subject subject = SecurityUtils.getSubject();
        try {
            //判断当日连续失败登陆次数是否超过5次
//            int count = errorService.count(new QueryWrapper<SysLoginError>()
//                    .eq("day", Util.currentDate()).eq("login_name", user.getLoginName()));
//            if(count>=5){
//                msg = "连续登陆失败次数超过5次, 账户已锁";
//                code = 103;
//            }else{
            if (1 == 1) {
                oldUser = userService.getUserByLoginName(user.getLoginName(), "1");
                if (oldUser == null) {
                    int closeCount = userService.count(new QueryWrapper<SysUser>().eq("login_name", user.getLoginName()).ne("status", "1"));
                    if (closeCount > 0) {
                        msg = "该账户已经被停用, 请联系管理员";
                        code = 104;
                    } else {
                        msg = "用户名不存在, 请重新输入！";
                        code = 104;
                    }
                } else {
                    if (oldUser.getPostType().equals("2")) {
                        msg = "非系统管理员，请用系统管理员登陆！";
                        code = 104;
                    }
                    if (!subject.isAuthenticated()) {
                        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                                user.getLoginName(),
                                user.getPassword()
                        );
                        subject.login(usernamePasswordToken);
                        //subject.getSession().setTimeout(43200000);//12个小时
                        subject.getSession().setTimeout(1800000);
                        //查询该用户所管辖的养老院信息
                        JSONObject pensionJson = orgService
                                .getAllAuthTypeOrganization(oldUser.getUserNo() + "", "4");
                        List<Map<String, Object>> pensionList = new ArrayList<>();
                        if (null != pensionJson && pensionJson.size()>0) {
                            getPensionName(pensionList, JSONArray.fromObject(pensionJson.get("children")));
                        }
                        if (null != pensionList && pensionList.size() > 0) {
                            Map<String, Object> currentPension = pensionList.get(0);
                            if (null != currentPension) {
                                user.setCurrentPensionNo(Constance.Null2EmptyTrim(currentPension.get("orgId")));
                            }
                        }
                        subject.getSession().setAttribute("user", user);
                        userService.updateLoginTime(user.getLoginName());
                        userService.loginSuccess(oldUser.getUserNo(), user.getLoginName());
                    }
                }
            }
        } catch (AuthenticationException e) {
            code = 101;
            msg = "密码错误, 请重新输入！";
            if (oldUser != null) {
                userService.loginError(oldUser.getUserNo(), oldUser.getLoginName());
            }
        } catch (AuthorizationException e) {
            msg = "没有权限";
            code = 102;
        } catch (Exception e) {
            e.printStackTrace();
        }
        obj.put("code", code);
        obj.put("msg", msg);
        return obj;
    }

    private void getPensionName(List<Map<String, Object>> pensionNameList, JSONArray pensionJson) {
        if (Util.isNull(pensionJson) || pensionJson.size()<=0) {
            return;
        }
        pensionJson.forEach(json -> {
            JSONObject jsonObject = JSONObject.fromObject(json);
            //组织类型 1-管理 2-服务中心 3-村/社区 4-养老机构

            if (Util.isNotNull(jsonObject.get("type")) && Util.isNotNull(jsonObject.get("parentOrgId"))) {
                if ("4".equals(jsonObject.get("type").toString()) && "1290".equals(jsonObject.get("parentOrgId").toString())) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", Util.isNull(jsonObject.get("orgName")) ? "" : jsonObject.get("orgName").toString());
                    map.put("orgId", Util.isNull(jsonObject.get("orgId")) ? "" : jsonObject.get("orgId").toString());
                    pensionNameList.add(map);
                }
            }
            if (Util.isNotNull(jsonObject.get("children"))) {
                getPensionName(pensionNameList, JSONArray.fromObject(jsonObject.get("children")));
            }
        });
    }


    @RequestMapping("/index")
    public String index(ModelMap model) throws Exception {
        //查询板块列表（排除平台管理）
        List<Map<String, Object>> appList = menuService.listMaps(new QueryWrapper<SysMenu>().select("name", "menu_no").eq("TYPE", "0").orderByAsc("sort"));
        appList.forEach(obj -> {
            obj.put("menu_no", DesUtil.encrypt(obj.get("menu_no") + ""));
        });
        //获取优先显示板块代码
        int initMenu = menuService.getFirstShowMenu(getUserNo());

        SysUser user = getUser();
        SysUser tmpUser = userService.getById(getUserNo());
        if (tmpUser == null) {
            throw new Exception("SysUser查询失败，userNo=" + getUserNo());
        }
        //查询养老机构列表
        //查询该用户所管辖的养老院信息
        JSONObject pensionJson = orgService
                .getAllAuthTypeOrganization(user.getUserNo() + "", "4");
        List<Map<String, Object>> pensionList = new ArrayList<>();
        if (null != pensionJson && pensionJson.size()>0) {
            getPensionName(pensionList, JSONArray.fromObject(pensionJson.get("children")));
        }
        model.put("pwdFlag", tmpUser.getPasswordEditFlag());
        model.put("userName", user.getUserName());
        model.put("userPhoto", user.getUserPhoto());
        model.put("userNo", DesUtil.encrypt(getUserNo() + ""));
        model.put("appList", appList);
        model.put("pensionList", pensionList);
        model.put("initMenu", DesUtil.encrypt(initMenu + ""));
        return "view/sys/index";
    }

    /**
     * 功能描述: 欢迎界面
     *
     * @Author: szt
     * @Date: 2020/12/8
     */
    @RequestMapping("/welcome")
    public String welcome() {
        return "view/sys/welcome";
    }

    /**
     * 功能描述: 未授权界面
     *
     * @Author: szt
     * @Date: 2020/12/8
     */
    @RequestMapping("/unauth")
    public String unauth() {
        return "view/sys/unauth";
    }

    //获取菜单
    //192.168.1.180:9999/ATPension/getMenuByUser?menuNo=B9FA51FEA72196F1
    @RequestMapping("/getMenuByUser")
    @ResponseBody
    public Result getMenuByUser(String menuNo) throws Exception {
        Object obj;
        try {
            String userNo = getUser().getUserNo() + "";
            //平台管理 服务中心 养老机构 数据看板
            obj = menuService.getUserMenu(Integer.parseInt(userNo), DesUtil.decrypt(menuNo));

            return ResultUtil.success(200, String.valueOf(getUserNo()), obj);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取用单失败！");
            throw new Exception("获取用单失败！");
        }
    }

    //重设密码
    //192.168.1.180:9999/ATPension/resetPsw
    @RequestMapping("/resetPsw")
    public String resetPwd(String phone, ModelMap model) {
        model.put("phone", phone);
        return "view/sys/resetPsw";
    }

    //重设密码
    //192.168.1.180:9999/ATPension/resetPswSuc
    @RequestMapping("/resetPswSuc")
    public String resetPswSuc() {
        return "view/sys/resetPswSuc";
    }

    //身份验证
    //192.168.1.180:9999/ATPension/identity
    @RequestMapping("/identity")
    public String identity(ModelMap model) {
        return "view/sys/identity";
    }

    //退出登录
    @RequestMapping("/outLogin")
    public String outLogin() throws Exception {
        SysUser oldUser = new SysUser();

        try {
            oldUser = userService.getById(getUserNo());

            //日志记录  sys 组织架构模块  sys-206 操作员退出
            SysLog log = new SysLog(getUserNo(), "1", "sys", "sys-206", "1", oldUser.getLoginName() + "登陆退出成功！", new Date());
            logService.save(log);
            ShiroUtil.logout();
            return "redirect:login";
        } catch (Exception e) {
            e.printStackTrace();
            //日志记录  sys 组织架构模块  sys-206 操作员退出
            SysLog log = new SysLog(getUserNo(), "1", "sys", "sys-206", "9", oldUser.getLoginName() + "登陆退出失败！", new Date());
            logService.save(log);
            throw new Exception("登陆退出失败！");
        }
    }

    //修改密码
    @RequestMapping("/changePassword")
    @ResponseBody
    public Result changePassword(String phone, String newPassword) {
        SysUser user = new SysUser();
        try {
            //重置密码
            user = userService.getOne(new QueryWrapper<SysUser>().eq("phone", phone).eq("post_type", "1"));

            String salt = Util.getStringRandom(20);
            String password = ShiroUtil.sha256(newPassword, salt);

            user.setPaw(newPassword);
            user.setPasswordEditFlag("1");
            user.setPassword(password);
            userService.updateById(user);
            //日志记录  sys 组织架构模块  sys-209 修改密码
            SysLog log = new SysLog(user.getUserNo(), "1", "sys", "sys-209", "1", user.getLoginName() + "修改用户密码成功！", new Date());
            logService.save(log);
            return ResultUtil.success(200, "密码修改成功！", userService.update(new UpdateWrapper<SysUser>().lambda().set(SysUser::getPaw, newPassword).set(SysUser::getSalt, salt).set(SysUser::getPassword, password).eq(SysUser::getUserNo, user.getUserNo())));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("密码修改失败！");
            //日志记录  sys 组织架构模块  sys-302 修改密码
            SysLog log = new SysLog(user.getUserNo(), "1", "sys", "sys-209", "9", user.getLoginName() + "修改用户密码失败！", new Date());
            logService.save(log);
            return ResultUtil.error(199, "密码修改失败！");
        }
    }

    /**
     * 功能描述：切换养老机构
     *
     * @Author GZ
     * @Date 2020/12/9 16:55
     */
    @RequestMapping("/changePensionInfo")
    @ResponseBody
    public JSONObject changePensionInfo(String pensionNo) {
        JSONObject object = new JSONObject();
        SysUser user = getUser();
        user.setCurrentPensionNo(pensionNo);
        Subject subject = SecurityUtils.getSubject();
        subject.getSession().setAttribute("user", user);
        object.put("code", "0000");
        object.put("codeDesc", "切换成功");
        return object;
    }
}
